package com.quark.common.security;

import cn.hutool.json.JSONUtil;
import com.quark.common.security.code.VerifyCodeFilter;
import com.quark.common.security.handler.MyAuthenticationFailureHandler;
import com.quark.common.security.handler.MyAuthenticationSuccessHandler;
import com.quark.common.security.handler.SsoLogoutSuccessHandler;
import com.quark.component.JwtAuthenticationTokenFilter;
import com.quark.component.RestAuthenticationEntryPoint;
import com.quark.component.RestfulAccessDeniedHandler;
import com.quark.result.RequestResult;
import com.quark.service.UmsAdminServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 张高昌
 * @date 2021/11/6 15:25
 * @description SpringSecurity的配置
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;

    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Autowired
    private UmsAdminServiceImpl umsAdminService;

    @Autowired
    private VerifyCodeFilter verifyCodeFilter;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/login/doLogin",
                "/login/loginOut",
                "/imgCode",
                "/css/**",
                "/js/**",
                "/index.html",
                "favicon.ico",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources/**",
                "/v2/api-docs/**"
        );
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
        http.formLogin().successHandler(myAuthenticationSuccessHandler)
                //因为前端传过来的是loginname
                .usernameParameter("loginame")
                .failureHandler(myAuthenticationFailureHandler)
                .permitAll();
        //关闭跨域攻击
        http.csrf().disable();
        //基于token，不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //授权
        http.authorizeRequests()
                //允许访问
                .antMatchers("/login/logout").permitAll()
                //除了上面，所有请求都要验证
//                .anyRequest().access("@rbacService.hasPermission(request,authentication)")
                .anyRequest().authenticated()
                .and()
                .logout()
//                .logoutUrl("/logout")
                //退出成功，返回json
                .logoutSuccessHandler((request,response,authentication) -> {
                    Map<String,Object> map = new HashMap<String,Object>();
                    map.put("code",200);
                    map.put("message","退出成功");
                    map.put("data",authentication);
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(JSONUtil.parse(RequestResult.success(map)).toStringPretty());
                    out.flush();
                    out.close();
                })
                //关闭缓存
                .and().headers().cacheControl();
        //添加jwt 登录过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加自定义未授权和未登录结果返回
        http.exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(umsAdminService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

//    @Bean
//    public AuthenticationFailureHandler authenticationFailureHandler() {
//        return new FormAuthenticationFailureHandler();
//    }

    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() {
        return new SsoLogoutSuccessHandler();
    }

//    @Bean
//    public AuthenticationEventPublisher authenticationEventPublisher
//            () {
//        return new DefaultAuthenticationEventPublisher();
//    }

//    @Bean
//    @Override
//    public AuthenticationManager authenticationManagerBean() throws Exception {
//        return super.authenticationManagerBean();
//    }

//
//
//    /**
//     * 没有权限访问时
//     *
//     * @return
//     */
//    @Bean
//    public RestfulAccessDeniedHandler restfulAccessDeniedHandler() {
//        return new RestfulAccessDeniedHandler();
//    }
//
//    /**
//     * 未登录或登录过期
//     *
//     * @return
//     */
//    @Bean
//    public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
//        return new RestAuthenticationEntryPoint();
//    }
//
//    /**
//     * 用于配置白名单资源路径
//     *
//     * @return
//     */
//    @Bean
//    public IgnoreUrlsConfig ignoreUrlsConfig() {
//        return new IgnoreUrlsConfig();
//    }
//
//    @Bean
//    public JwtTokenManager jwtTokenUtil() {
//
//        return new JwtTokenManager();
//    }

//    @Override
//    @Bean
//    public UserDetailsService userDetailsService() {
//        //获取登录用户信息
//        return userName -> sysUserMapper.selectByUserName(userName);
//    }

}
